package atom;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * AtomicIntegerFieldUpdater 将对象下的属性原子化，使其线程安全
 */
public class AtomicIntegerFieldUpdaterTest {

  // AtomicIntegerFieldUpdater is registered with Details.class so that it
  // knows it will later be updating the volatile field called
  // numberTimesInvoked
  //步骤1 构造方法
  private AtomicIntegerFieldUpdater<Details>
          atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(
          Details.class, "numberTimesInvoked");


  /**
   * Diferent threads can call this method to update the volatile field of
   * an instance of Details
   *
   * @param details Details object which has the volatile field called
   *                "numberTimesInvoked" in it.
   * @return the value of the counter after it has been incremented by one
   */
  //步骤2 对AtomicIntegerFieldUpdater修饰的变量进行操作
  public int addOne(Details details) {

    // performs a "x = x + 1" style atomic operation
    //return atomicIntegerFieldUpdater.addAndGet( details, 1 );
    return this.atomicIntegerFieldUpdater.getAndIncrement(details);
  }

  public int subOne(Details details) {
    return atomicIntegerFieldUpdater.decrementAndGet(details);
  }


  /**
   * See test class for example of using this class with multiple threads,
   * some of which are writing to the volatile field and some which are
   * reading from the volatile field
   *
   * @throws InterruptedException
   */
  public static void main(String[] args) throws InterruptedException {

    final AtomicIntegerFieldUpdaterTest atomicIntegerFieldUpdaterCounter =
            new AtomicIntegerFieldUpdaterTest();

    // This call would ordinarily be made by many other threads
    final Details d = new Details();
    System.out.print("对象d的变量numberTimesInvoked累计前:" + d.getNumberTimesInvoked());
    System.out.println(",A累计前：" + AtomicIntegerTest.A);
    Thread t0 = new Thread(
            new Runnable() {

              @Override
              public void run() {
                for (int j = 0; j < 100000; j++) {

                  atomicIntegerFieldUpdaterCounter.addOne(d);
                  AtomicIntegerTest.A++;
                }
              }
            });
    Thread t1 = new Thread(
            new Runnable() {

              @Override
              public void run() {
                for (int j = 0; j < 100000; j++) {
                  AtomicIntegerTest.A++;
                  atomicIntegerFieldUpdaterCounter.subOne(d);
                }
              }
            });
    t0.start();
    t1.start();
    t0.join();
    t1.join();

    System.out.print("对象d的变量numberTimesInvoked累计后:" + d.getNumberTimesInvoked());
    System.out.println(",A累计后：" + AtomicIntegerTest.A);
  }

  static class Details {

    volatile int numberTimesInvoked;

    public int getNumberTimesInvoked() {

      return numberTimesInvoked;
    }

    public void setNumberTimesInvoked(int numberTimesInvoked) {

      this.numberTimesInvoked = numberTimesInvoked;
    }
  }
}
